// 全局变量是在所有其他作用域之外声明的。
use std::convert::From;
use std::convert::TryFrom;
use std::fmt;
use std::string::String;

static LANGUAGE: &'static str = "Rust";
const THRESHOLD: i32 = 10;

#[allow(dead_code)]
fn is_big(n: i32) -> bool {
    // 在一般函数中访问常量
    n > THRESHOLD
}

#[derive(Debug, PartialEq)]
struct Number {
    value: i32,
}

impl From<i32> for Number {
    fn from(item: i32) -> Self {
        Number { value: item }
    }
}

#[derive(Debug, PartialEq)]
struct EvenNumber {
    value: i32,
}

// #[derive(Debug, PartialEq)]
// struct EvenNumber(i32);

impl TryFrom<i32> for EvenNumber {
    type Error = ();
    fn try_from(value: i32) -> Result<Self, Self::Error> {
        if value % 2 == 0 {
            Ok(EvenNumber { value })
        } else {
            Err(())
        }
    }
}

// impl Into<i32> for Number {
//     fn into(self) -> i32 {
//         self.value
//     }
// }

fn main() {
    // #[allow(dead_code)]
    let _name = "Rust";
    println!("CONST THRESHOLD value : {}", THRESHOLD);
    println!("STATIC LANGUAGE value : {}", LANGUAGE);
    // 字符串
    // strings();

    // int and float
    // int_and_floats();

    // 数组
    // array();

    // 元组匹配模式
    // tuple_match();

    // 常规运算
    // calc();

    //  字符串拆分
    // string_split();

    // 可变变量();
    // variable_change();

    // From 转换
    // from_into_test();

    // TryFrom and TryInto
    // try_from_and_try_into_test();

    // 字符串转换
    // to_string_test();

    // 变量作用域
    // variable_scope();

    // 变量冻结
    // variable_freeze();

    // 表达式
    // variable_expression();

    // 引用
    reference_test();
}

#[allow(dead_code)]
fn reference_test() {
    let x = 5;
    let y = &x;

    println!("x is :{}", x);
    println!("y is :{}", y);

    // 引用不能被修改
    // y = 10;

    // 引用可以被解引用
    println!("y value is :{}", *y);

    // 引用可以被解引用
    println!("y value is :{}", y.clone());

    // 获得一个 `i32` 类型的引用。`&` 表示取引用。
    let reference = &4;

    match reference {
        // 如果用 `&val` 这个模式去匹配 `reference`，就相当于做这样的比较：
        // `&i32`（译注：即 `reference` 的类型）
        // `&val`（译注：即用于匹配的模式）
        // ^ 我们看到，如果去掉匹配的 `&`，`i32` 应当赋给 `val`。
        // 译注：因此可用 `val` 表示被 `reference` 引用的值 4。
        &val => println!("Got a value via destructuring: {:?}", val),
    }

    // 如果不想用 `&`，需要在匹配前解引用。
    match *reference {
        val => println!("Got a value via dereferencing: {:?}", val),
    }

    // 如果一开始就不用引用，会怎样？ `reference` 是一个 `&` 类型，因为赋值语句
    // 的右边已经是一个引用。但下面这个不是引用，因为右边不是。
    let _not_a_reference = 3;

    // Rust 对这种情况提供了 `ref`。它更改了赋值行为，从而可以对具体值创建引用。
    // 下面这行将得到一个引用。
    let ref _is_a_reference = 3;

    // 相应地，定义两个非引用的变量，通过 `ref` 和 `ref mut` 仍可取得其引用。
    let value = 5;
    let mut mut_value = 6;

    // 使用 `ref` 关键字来创建引用。
    // 译注：下面的 r 是 `&i32` 类型，它像 `i32` 一样可以直接打印，因此用法上
    // 似乎看不出什么区别。但读者可以把 `println!` 中的 `r` 改成 `*r`，仍然能
    // 正常运行。前面例子中的 `println!` 里就不能是 `*val`，因为不能对整数解
    // 引用。
    match value {
        ref r => println!("Got a reference to a value: {:?}", r),
    }

    // 类似地使用 `ref mut`。
    match mut_value {
        ref mut m => {
            // 已经获得了 `mut_value` 的引用，先要解引用，才能改变它的值。
            *m += 10;
            println!("We added 10. `mut_value`: {:?}", m);
        }
    }
}

#[allow(dead_code)]
fn variable_expression() {
    let x = 5u32;

    let y = {
        let x_squared = x * x;
        let x_cube = x_squared * x;

        // 将此表达式赋给 `y`
        x_cube + x_squared + x
    };

    let z = {
        // todo  分号结束了这个表达式，于是将 `()` 赋给 `z`
        // println!("zx value is :{}", x);
        2 * x
    };

    println!("x is {:?}", x);
    println!("y is {:?}", y);
    println!("z is {:?}", z);
}

#[allow(dead_code)]
fn variable_freeze() {
    let mut _mutable_integer = 7;
    {
        // 被不可变的 `_mutable_integer` 遮蔽
        let _mutable_integer = _mutable_integer;
        println!("freeze integer: {}", _mutable_integer);

        // 报错！`_mutable_integer` 在本作用域被冻结
        // _mutable_integer = 50;
        // 改正 ^ 注释掉上面这行

        // `_mutable_integer` 离开作用域
    }

    // 正常运行！ `_mutable_integer` 在这个作用域没有冻结
    _mutable_integer = 3;

    println!("mutable integer: {}", _mutable_integer);

    // -1 + 256 = 255
    println!("  -1 as a u8 is : {}", (-1i8) as u8);
}

#[allow(dead_code)]
fn variable_scope() {
    // 此绑定生存于 main 函数中
    let mut long_lived_binding = 1;

    // 这是一个代码块，比 main 函数拥有更小的作用域
    {
        // 此绑定只存在于本代码块
        let short_lived_binding = 2;

        println!("inner short: {}", short_lived_binding);

        println!("out variable1: {}", long_lived_binding);

        long_lived_binding = 5;
        println!("out variable2: {}", long_lived_binding);

        // 此绑定*遮蔽*了外面的绑定
        let long_lived_binding = 5_f32;
        println!("inner long: {}", long_lived_binding);
    }
    // 代码块结束

    // 报错！`short_lived_binding` 在此作用域上不存在
    // println!("outer short: {}", short_lived_binding);
    // 改正 ^ 注释掉这行

    println!("outer long: {}", long_lived_binding);

    // 此绑定同样*遮蔽*了前面的绑定
    let long_lived_binding = 'a';

    println!("outer long: {}", long_lived_binding);
}

#[allow(dead_code)]
fn to_string_test() {
    struct CircleDisplay {
        radius: f64,
    }

    struct CircleString {
        radius: f64,
    }

    impl fmt::Display for CircleDisplay {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "CircleDisplay with radius: {}", self.radius)
        }
    }

    impl ToString for CircleString {
        fn to_string(&self) -> String {
            format!("CircleString of radius {:?}", self.radius)
        }
    }

    let circle = CircleDisplay { radius: 10.0 };
    let circle2 = CircleString { radius: 10.0 };
    println!("{}", circle);
    println!("{}", circle2.to_string());
}

#[allow(dead_code)]
fn try_from_and_try_into_test() {
    // TryFrom
    assert_eq!(EvenNumber::try_from(10), Ok(EvenNumber { value: 10 }));
    assert_eq!(EvenNumber::try_from(5), Err(()));

    // TryInto
    let result: Result<EvenNumber, ()> = 8i32.try_into();
    assert_eq!(result, Ok(EvenNumber { value: 8 }));
    let result2: Result<EvenNumber, ()> = 5i32.try_into();
    assert_eq!(result2, Err(()));
    // assert_eq!(10i32.try_into(), Ok(Number { value: 10 }));
}

#[allow(dead_code)]
fn from_into_test() {
    let my_str = "hello";
    let my_string = String::from(my_str);
    println!("{}", my_string);

    let my_num = Number::from(10);
    println!("{:?}", my_num);

    //  into
    let num = 22;
    let num2: Number = num.into();
    print!("num into value is: {:?}", num2);
}

#[allow(dead_code)]
fn variable_change() {
    let _immutable_binding = 1;
    let mut mutable_binding = 1;

    println!("Before mutation: {}", mutable_binding);

    // 正确代码
    mutable_binding += 1;

    println!("After mutation: {}", mutable_binding);

    // 错误！
    // _immutable_binding += 1;
    // 改正 ^ 将此行注释掉
}

#[allow(dead_code)]
fn string_split() {
    let s = "Hello, world! 99 55  6";
    #[allow(unused_variables, dead_code)]
    let words = s.split('-');

    // 迭代器
    for word in words {
        println!("{}", word);
    }

    // 遍历 x
    // for word in &s.split(' ') {
    //     println!("{}", word);
    // }

    // 遍历并修改 x
    // for word in s.split_mut(' ') {
    //     *word = word.to_uppercase();
    // }

    println!("{}", s);

    // demo 1
    let location = String::from(
        "/sso.iam.local/auth/admin/realms/xxx/groups/c1bf8486-4c7c-4669-9939-ab765e5699e1",
    );
    let pos: Vec<&str> = location.split("/").collect();
    // println!("id: {}", pos[pos.len() - 1]);
    // 遍历
    for word in pos {
        println!("{}", word);
    }

    //demo 2
    let location = String::from(
        "/sso.iam.local/auth/admin/realms/xxx/groups/c1bf8486-4c7c-4669-9939-ab765e5699e1",
    );
    let pos = location.rfind("/").unwrap();
    let (_, lst) = location.split_at(pos + 1);
    println!("id:{}", lst);
}

#[allow(dead_code)]
fn calc() {
    println!("1+2={}", 1i32 + 2);
    // 整数相减
    println!("1 - 2 = {}", 1i32 - 2);
    // 试一试 ^ 尝试将 `1i32` 改为 `1u32`，体会为什么类型声明这么重要

    // 短路求值的布尔逻辑
    println!("true AND false is {}", true && false);
    println!("true OR false is {}", true || false);
    println!("NOT true is {}", !true);

    // 位运算
    println!("0011 AND 0101 is {:04b}", 0b0011u32 & 0b0101);
    println!("0011 OR 0101 is {:04b}", 0b0011u32 | 0b0101);
    println!("0011 XOR 0101 is {:04b}", 0b0011u32 ^ 0b0101);
    println!("1 << 5 is {}", 1u32 << 5);
    println!("0x80 >> 2 is 0x{:x}", 0x80u32 >> 2);

    // 使用下划线改善数字的可读性！
    println!("One million is written as {}", 1_000_000u32);
}

#[allow(dead_code)]
fn tuple_match() {
    //匹配模式
    let person: (bool, i32, f64) = (true, 30, 5.8);

    match person {
        (name, age, height) => {
            println!("Name: {}, Age: {}, Height: {}", name, age, height);
            // 输出：Name: true, Age: 30, Height: 5.8
        }
    };
}

#[allow(dead_code)]
fn string_to_int() {
    let x = "5".parse::<i32>();

    match x {
        Ok(i) => println!("The value of x is: {}", i),
        Err(e) => println!("There was a problem converting x: {}", e),
    }
}

#[allow(dead_code)]
fn int_to_string() {
    let x = 5;

    let s = x.to_string();

    println!("The value of x is: {}", s);
}

#[allow(dead_code)]
fn int_to_float() {
    let x = 2;

    let y = x as f64;

    println!("The value of y is: {}", y);
}

#[allow(dead_code)]
fn float_to_int() {
    let x = 2.0;

    let y = x as i32;

    println!("The value of y is: {}", y);
}

#[allow(dead_code)]
fn int_and_floats() {
    let x = 2.0; // f64

    let mut y: f32 = 3.0; // f32

    y = y + 1 as f32;

    println!("x is {}, y is {}", x, y);
}

#[allow(dead_code)]
fn strings() {
    let mut s = String::from("hello");

    s.push_str(", world!");

    println!("{}", s);

    let s1 = "hello";
    let s2 = "world";
    let s3 = s1.to_string() + ", " + s2;

    println!("{}", s3);

    let s = "hello";

    let len = s.len();

    println!("The length of '{}' is {}.", s, len);

    // let s = "hello";
}
